<template>
  <div class="container">
    <div id="vue-three"></div>
  </div>
</template>

<script>
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
// 导入字体加载器
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
// 导入文本几何体生成器
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';

let _this;
export default {
  data() {
    return {
      mouseX: 0,
      mouseY: 0,
      isMouseDown: false,
      prevMouseX: 0,
      prevMouseY: 0,

      scene: null,
      camera: null,
      renderer: null,
      mouse: new THREE.Vector2(1, 1),
      controls: null,
    }
  },
  mounted() {
    // this.initThree()
    this.draw();
    this.addEventListeners();
    _this = this;
  },
  methods: {
    //构建虚拟场景
    initThree() {
      //场景
      var scene = new THREE.Scene()

      // 透视相机(// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000：远裁截面)
      var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 2000)
      // camera.position.z = 5//position：相机位置xyz坐标：200, 200, 200
      camera.position.set(10.0, 20, 13)
      camera.up.set(0, 0, 1)
      camera.lookAt(new THREE.Vector3(0, 0, 0))

      // 渲染器
      var renderer = new THREE.WebGLRenderer()
      renderer.setSize(window.innerWidth, window.innerHeight)
      let dom = document.getElementById('vue-three')
      dom.appendChild(renderer.domElement)//添加进页面

      // AxesHelper：辅助观察的坐标系
      const axesHelper = new THREE.AxesHelper(150)
      scene.add(axesHelper)

      //网格线绘制
      var grid = new THREE.GridHelper(24, 24, 0xFF0000, 0x444444)
      grid.material.opacity = 0.4
      grid.material.transparent = true
      grid.rotation.x = Math.PI / 2.0
      scene.add(grid)

      // 材质
      const material = new THREE.MeshBasicMaterial({
        color: 0x0000ff, //设置材质颜色
        transparent: true,//开启透明
        opacity: 0.5,//设置透明度
      })

      // 设置几何体长宽高，也就是x、y、z三个方向的尺寸
      //对比三个参数分别对应xyz轴哪个方向
      var geometry = new THREE.BoxGeometry(2, 2, 2)

      //点光源：两个参数分别表示光源颜色和光照强度
      // 参数1：0xffffff是纯白光,表示光源颜色
      // 参数2：1.0,表示光照强度，可以根据需要调整
      const pointLight = new THREE.PointLight(0xffffff, 1.0)
      pointLight.decay = 0.0//设置光源不随距离衰减
      pointLight.position.set(400, 200, 300) //点光源放在x轴上
      scene.add(pointLight)

      // 物体
      var cube = new THREE.Mesh(geometry, material)
      scene.add(cube)

      function animate() {
        requestAnimationFrame(animate)
        cube.rotation.x += 0.01
        cube.rotation.y += 0.01
        renderer.render(scene, camera)
      }

      animate()
    },

    draw() {
      // 创建3D场景对象Scene
      this.scene = new THREE.Scene();


      //创建一个长方体几何对象Geometry
      const geometry = new THREE.BoxGeometry(20, 20, 20);
      //创建一个材质对象Material
      const material = new THREE.MeshBasicMaterial({
        color: 0x082966,//0xff0000设置材质颜色为红色
        transparent: true,//开启透明
        opacity: 0.5,//设置透明度
      });
      // 两个参数分别为几何体geometry、材质material
      const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      //设置网格模型在三维空间中的位置坐标，默认是坐标原点
      mesh.position.set(20, 10, 0);
      // scene.add(mesh);


      const width = window.innerWidth - 100; //宽度
      const height = window.innerHeight - 100; //高度

      // 实例化一个透视投影相机对象
      this.camera = new THREE.PerspectiveCamera(80, width / height, 0.1, 1000);
      this.camera.position.set(0, 0, 20)
      this.camera.up.set(0, 0, 1)
      this.camera.lookAt(new THREE.Vector3(0, 0, 0))

      // AxesHelper：辅助观察的坐标系
      const axesHelper = new THREE.AxesHelper(20);
      this.scene.add(axesHelper);

      // 创建用于划分空间的线段,X.Y.Z画线
      const xLineMaterial = new THREE.LineBasicMaterial({color: 0xCD4335});
      const xGeometryLine = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(-20, 0, 0)]);
      const xLines = new THREE.Line(xGeometryLine, xLineMaterial);
      this.scene.add(xLines);

      const yLineMaterial = new THREE.LineBasicMaterial({color: 0x69E300});
      const yGeometryLine = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, -20, 0)]);
      const yLines = new THREE.Line(yGeometryLine, yLineMaterial);
      this.scene.add(yLines);

      const zLineMaterial = new THREE.LineBasicMaterial({color: 0x004272});
      const zGeometryLine = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, -20)]);
      const zLines = new THREE.Line(zGeometryLine, zLineMaterial);
      this.scene.add(zLines);


      // 创建中心四个面
      const planeMaterial1 = new THREE.MeshBasicMaterial({
        color: 0x1abc9c,
        side: THREE.DoubleSide,
        transparent: true,//开启透明
        opacity: 0.3,//设置透明度
      });
      const planeMaterial2 = new THREE.MeshBasicMaterial({
        color: 0xff7f50,
        side: THREE.DoubleSide,
        transparent: true,//开启透明
        opacity: 0.3,//设置透明度
      });
      const planeMaterial3 = new THREE.MeshBasicMaterial({
        color: 0x74b9ff,
        side: THREE.DoubleSide,
        transparent: true,//开启透明
        opacity: 0.3,//设置透明度
      });
      const planeGeometry = new THREE.PlaneGeometry(20, 20);
      const planes = [
        new THREE.Mesh(planeGeometry, planeMaterial1),
        // new THREE.Mesh(planeGeometry, planeMaterial2).rotateY(Math.PI / 2),
        // new THREE.Mesh(planeGeometry, planeMaterial3).rotateZ(Math.PI / 2)
      ];
      planes.forEach(plane => this.scene.add(plane));


      //网格线绘制
      this.gridHelper();



      // 创建渲染器对象
      this.renderer = new THREE.WebGLRenderer();
      //设置three.js渲染区域的尺寸(像素px)
      this.renderer.setSize(width, height);
      // 设置背景色为白色
      this.renderer.setClearColor(0xffffff);
      document.getElementById('vue-three').appendChild(this.renderer.domElement);


      // 360°旋转
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.enableDamping = true//设置阻尼惯性
      this.controls.dampingFactor = 0.05//设置阻尼系数
      this.controls.autoRotate = true//开启坐标轴自动旋转
      this.controls.enableZoom = false;
      this.controls.enablePan = false;


      this.renderer.render(this.scene, this.camera)
    },

    addEventListeners() {
      document.addEventListener('mousedown', this.onMouseDown);
      document.addEventListener('mousemove', this.onMouseMove);
      document.addEventListener('mouseup', this.onMouseUp);
      // 添加 passive: false 选项
      document.addEventListener('wheel', this.onWheel, { passive: false });
    },

    onMouseDown(event) {
      this.isMouseDown = true;
      this.mouseX = event.clientX;
      this.mouseY = event.clientY;
    },

    onMouseMove(event) {
      if (this.isMouseDown) {
        this.controls.update();
        this.renderer.render(this.scene, this.camera);
      }
    },

    onMouseUp() {
      this.isMouseDown = false;
    },

    onWheel(event) {
      let scaleFactor = 1.1;
      event.preventDefault();
      const delta = event.deltaY > 0 ? 1 / scaleFactor : scaleFactor;
      this.camera.position.multiplyScalar(delta);
      this.renderer.render(this.scene, this.camera);
    },


    // 网格线绘制
    gridHelper(){
      var grid = new THREE.GridHelper(24, 24, 0xFF0000, 0x444444)
      grid.material.opacity = 0.4
      grid.material.transparent = true
      grid.rotation.x = Math.PI / 2.0
      this.scene.add(grid)
      // // 创建字体加载器
      // const fontLoader = new FontLoader();
      // // 加载字体（这里使用的是 Three.js 示例中的字体文件，你需要根据实际情况调整路径）
      // fontLoader.load('/font/helvetiker_regular.typeface.json', (font) => {
      //   // 在特定位置创建文本几何体表示坐标点
      //   const textGeometry1 = new TextGeometry('(0, 0)', {
      //     font: font,
      //     size: 0.1,
      //     height: 0.01,
      //   });
      //   const material1 = new THREE.MeshBasicMaterial({ color: 0x000000 });
      //   const textMesh1 = new THREE.Mesh(textGeometry1, material1);
      //   textMesh1.position.set(0, 0 - 0.1, 0.1);
      //   textMesh1.rotation.z = Math.PI / 2;
      //   _this.scene.add(textMesh1);
      //
      //   const textGeometry2 = new TextGeometry('(1, 1)', {
      //     font: font,
      //     size: 0.1,
      //     height: 0.01,
      //   });
      //   const material2 = new THREE.MeshBasicMaterial({ color: 0x000000 });
      //   const textMesh2 = new THREE.Mesh(textGeometry2, material2);
      //   textMesh2.position.set(1, 1 - 0.1, 0.1);
      //   textMesh2.rotation.z = Math.PI / 2;
      //   _this.scene.add(textMesh2);
      // });
    },


    animate() {
      requestAnimationFrame(this.animate)
      this.renderer.render(this.scene, this.camera)
    }
  }


}
</script>
<style scoped>
.container {
  width: 100%;
  height: 100%;
}

#vue-three {
  position: relative;
}
</style>


